#include "gwrectangle.h"

#include <QGraphicsView>
#include <QPainter>
#include <QRect>
#include <QDebug>
#include <QGraphicsSceneMouseEvent>

static constexpr int resizeHandleWidth = 6;

QGradient GwRectangle::gradient(const QColor &color, const QRectF &rect,int time)
{
    QColor c = color;
    int x0,x1,y0,y1,s0;
    float vall,t1;
    x0=rect.left();
    x1=rect.right();
    y0=rect.top();
    y1=rect.bottom();
    c.setAlpha(150);
    QLinearGradient result(rect.topLeft(), rect.bottomRight());
    vall=((float)(x1-x0)+(y1-y0))/range;
    t1=(x1-x0)/vall;
    if(time<=t1)
    {
        s0=vall*time;
        result.setStart(s0,y0);
        result.setFinalStop((x1-s0),y1);
    }
    else
    {
        s0=vall*(time-t1);
        result.setStart(x1,s0);
        result.setFinalStop(x0,(y1-s0));
    }

    result.setColorAt(0, c.darker(120));
    result.setColorAt(0.5, c.lighter(200));
    result.setColorAt(1, c.darker(120));


    return result;
}

GwRectangle &GwRectangle::operator=(const GwRectangle &other)
{
    this->m_rect.setWidth(other.m_rect.width());
    this->m_rect.setHeight(other.m_rect.height());
    this->setPos(other.pos());
    this->name=other.name;
    this->gwfile=other.gwfile;
    return *this;
}


QDataStream & operator >>(QDataStream &in, GwRectangle &data)
{
    qreal width,height,x,y;
    QString name,gwfile;

    in>>width>>height>>x>>y>>name>>gwfile;
    data.m_rect.setWidth(width);
    data.m_rect.setHeight(height);
    QPointF cent=data.mapToScene(x,y);
    data.setPos(cent);
    data.name=name;
    data.gwfile=gwfile;
//    data.setName(name);
//    data.setGWFile(gwfile);
    return in;
}

QDataStream & operator <<(QDataStream &out, const GwRectangle &data)
{
    QPointF rec=data.mapToScene(data.m_rect.topLeft());
    out
    <<data.m_rect.width()
    <<data.m_rect.height()
    <<rec.x()
    <<rec.y()
    <<data.name
    <<data.gwfile;
    return out;
}


GwRectangle::GwRectangle()
{
    m_rect=QRectF(0, 0, 30, 30);
//    this->setFlags(ItemIsSelectable | ItemIsMovable);
//    this->setAcceptHoverEvents(true);
    this->createPropertyList();
    this->rect_colour=Qt::green;
    movie=new QTimeLine(500);
    movie->setFrameRange(0,range);
    movie->setLoopCount(0);
    this->setFlags(ItemIsSelectable);
    connect(movie,&QTimeLine::frameChanged,this,&GwRectangle::movieRun);
}

GwRectangle::GwRectangle(const GwRectangle &other)
{
    this->m_rect.setWidth(other.m_rect.width());
    this->m_rect.setHeight(other.m_rect.height());
    this->setPos(other.pos());
    this->name=other.name;
    this->gwfile=other.gwfile;
    this->setFlags(ItemIsSelectable);
//    this->setFlags(ItemIsSelectable | ItemIsMovable);
//    this->setAcceptHoverEvents(true);
    this->createPropertyList();
    this->rect_colour=Qt::green;
    movie=new QTimeLine(500);
    movie->setFrameRange(0,range);
    movie->setLoopCount(0);
    connect(movie,&QTimeLine::frameChanged,this,&GwRectangle::movieRun);
}

GwRectangle::~GwRectangle()
{
    this->movie->stop();
    delete this->movie;
    delete this->m_pVarFactory;
    delete this->m_pVarManager;
    delete this->m_stringFactory;
    delete this->m_stringManager;
}


QRectF GwRectangle::boundingRect() const
{
    qreal penWidth=0.5;
    return m_rect.adjusted(-penWidth,-penWidth,penWidth,penWidth);
}

QRectF GwRectangle::resizeHandle()
{
    QPointF br = m_rect.bottomRight();
    return QRectF(br - QPointF(resizeHandleWidth, resizeHandleWidth), br);
}

void GwRectangle::setName(QString name)
{
    this->name=name;
}

void GwRectangle::setGWFile(QString gwfile)
{
    this->gwfile=gwfile;
}

QString GwRectangle::getGWFile()
{
    return this->gwfile;
}

void GwRectangle::setPropertyTree(QtTreePropertyBrowser *treepro)
{
    QtProperty *item;
    treepro->clear();
    foreach(item, m_propertys)
    {
        this->refreshProperty(item);
        treepro->addProperty(item);
    }
    treepro->setFactoryForManager(m_pVarManager,m_pVarFactory);
    treepro->setFactoryForManager(m_stringManager,m_stringFactory);
}

void GwRectangle::refreshProperty(QtProperty *item)
{
    QPointF rec=this->mapToScene(this->m_rect.topLeft());
    if(item->propertyName()==QStringLiteral("宽度"))
        m_pVarManager->setValue(item,m_rect.width());
    else if(item->propertyName()==QStringLiteral("高度"))
        m_pVarManager->setValue(item,m_rect.height());
    else if(item->propertyName()==QStringLiteral("X"))
        m_pVarManager->setValue(item,rec.x());
    else if(item->propertyName()==QStringLiteral("Y"))
        m_pVarManager->setValue(item,rec.y());
    else if(item->propertyName()==QStringLiteral("名称"))
        m_pVarManager->setValue(item,this->name);
    else if(item->propertyName()==QStringLiteral("链接组态"))
        m_stringManager->setValue(item,this->gwfile);
}

void GwRectangle::refreshPropertyList()
{
    QtProperty *item;
    foreach (item, m_propertys) {
        this->refreshProperty(item);
    }
}

void GwRectangle::createPropertyList()
{
    if(m_pVarManager!=NULL)
    {
        m_pVarManager->clear();
        delete m_pVarManager;
    }
    if(m_pVarFactory!=NULL)
    {
        delete m_pVarFactory;
    }
    if(m_property_dic.count()>0)
    {
        m_property_dic.clear();
    }
    this->m_pVarManager =new QtVariantPropertyManager();
    this->m_pVarFactory=new QtVariantEditorFactory();

    this->m_stringManager=new QtStringPropertyManager();
    this->m_stringFactory=new fileEditFactory();

    QtProperty *item =m_pVarManager->addProperty(QVariant::Int, QStringLiteral("宽度"));
    m_property_dic[item] =QStringLiteral("宽度");
    m_pVarManager->setValue(item,m_rect.width());
//    item->setValue(m_rect.width());
    m_propertys.append(item);

    item =m_pVarManager->addProperty(QVariant::Int, QStringLiteral("高度"));
    m_property_dic[item] =QStringLiteral("高度");
    m_pVarManager->setValue(item,m_rect.height());
//    item->setValue(m_rect.height());
    m_propertys.append(item);

    item =m_pVarManager->addProperty(QVariant::Int, QStringLiteral("X"));
    m_property_dic[item] =QStringLiteral("X");
    m_pVarManager->setValue(item,m_rect.x());
//    item->setValue(m_rect.x());
    m_propertys.append(item);

    item =m_pVarManager->addProperty(QVariant::Int, QStringLiteral("Y"));
    m_property_dic[item] =QStringLiteral("Y");
    m_pVarManager->setValue(item,m_rect.y());
//    item->setValue(m_rect.y());
    m_propertys.append(item);

    item =m_pVarManager->addProperty(QVariant::String, QStringLiteral("名称"));
    m_property_dic[item] =QStringLiteral("名称");
    m_pVarManager->setValue(item,"");
    m_propertys.append(item);


    item=m_stringManager->addProperty(QStringLiteral("链接组态"));
    m_stringManager->setValue(item,"");
    m_propertys.append(item);

    QtVariantProperty *varitem = m_pVarManager->addProperty(QtVariantPropertyManager::enumTypeId(),
                    QStringLiteral("测试状态"));
    QStringList enumNames;
    enumNames << "正常" << "低报" << "高报";
    varitem->setAttribute(QStringLiteral("enumNames"), enumNames);
    varitem->setValue(0);
    m_propertys.append(varitem);


    connect(m_pVarManager,&QtVariantPropertyManager::valueChanged,this,&GwRectangle::propertyChanged);
    connect(m_stringManager,&QtStringPropertyManager::valueChanged,this,&GwRectangle::propertyChanged);

}

GraphicsState GwRectangle::state()
{
    return this->itemstate;
}

QRectF GwRectangle::rect()
{
    return this->m_rect;
}

void GwRectangle::setConfig()
{
    this->setFlags(ItemIsSelectable | ItemIsMovable);
    this->setAcceptHoverEvents(true);
}



void GwRectangle::propertyChanged(QtProperty *property, const QVariant &val)
{
    QPointF cent=mapToScene(this->m_rect.topLeft());
    if(property->propertyName()==QStringLiteral("宽度")){
        this->m_rect.setWidth(val.toInt());
    }
    else if(property->propertyName()==QStringLiteral("高度")){
        this->m_rect.setHeight(val.toInt());
    }
    else if(property->propertyName()==QStringLiteral("X")){
        cent.setX(val.toInt());
        this->setPos(cent);
    }
    else if(property->propertyName()==QStringLiteral("Y")){
        cent.setY(val.toInt());
        this->setPos(cent);
    }
    else if(property->propertyName()==QStringLiteral("名称")){
        this->name=val.toString();
    }
    else if(property->propertyName()==QStringLiteral("链接组态")){
        this->gwfile=val.toString();
    }
    else if(property->propertyName()==QStringLiteral("测试状态")){
        qDebug()<<m_pVarManager->value(property).toString();
        switch(m_pVarManager->value(property).toInt())
        {
        case 0:
            this->setState(GState_OK);
            break;
        case 1:
            this->setState(GState_LO);
            break;
        case 2:
            this->setState(GState_HI);
            break;
        }
    }
    scene()->update();
}

void GwRectangle::movieRun(int frame)
{
    flash=frame;
    this->update();
}

void GwRectangle::setState(GraphicsState state)
{
    this->itemstate=state;
    switch (state) {
    case GState_OK:
//        this->movie->setDuration(500);
        if(this->movie->state()==QTimeLine::Running)
            this->movie->stop();
        this->flash=0;
        this->rect_colour=Qt::green;
        break;
    case GState_LO:
        this->movie->setDuration(1200);
        this->flash=0;
        this->rect_colour=Qt::yellow;
        if(this->movie->state()!=QTimeLine::Running)
            this->movie->start();
        break;
    case GState_HI:
        this->movie->setDuration(600);
        this->flash=0;
        this->rect_colour=Qt::red;
        if(this->movie->state()!=QTimeLine::Running)
            this->movie->start();
        break;
    default:
        break;
    }
    this->update();
}

void GwRectangle::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    QPen pen;
    pen.setColor(Qt::black);
    if(this->isSelected())
        pen.setWidth(2);
    else
        pen.setWidth(1);
    painter->setPen(pen);
//    painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
    painter->setBrush(gradient(this->rect_colour, m_rect,flash));

    painter->drawRect(m_rect);
    painter->drawText(m_rect,Qt::AlignCenter,this->name);

    if(this->flags().testFlag(ItemIsMovable))
    {
        painter->setBrush(Qt::white);
        painter->drawRect(this->resizeHandle());
    }
}



void GwRectangle::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    if(!this->scene()->collidingItems(this).isEmpty())
    {
        if(this->colldingCnt<30)
        {
            this->colldingCnt++;
            return;
        }
    }
    else
    {
        this->colldingCnt=0;
    }
    if (m_resizeHandlePressed) {
        QPointF sizechange=event->scenePos()-m_mouseOffset;

        if(m_oldrect.height()+sizechange.y()<=resizeHandleWidth)
            sizechange.setY(m_oldrect.height()-resizeHandleWidth);
        if(m_oldrect.width()+sizechange.x()<=resizeHandleWidth)
            sizechange.setX(m_oldrect.width()-resizeHandleWidth);
        m_rect.setBottomRight(m_oldrect.bottomRight()+sizechange);
        this->prepareGeometryChange();
        this->scene()->update();
    }
    else
        QGraphicsItem::mouseMoveEvent(event);
    this->refreshPropertyList();
}


void GwRectangle::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    if(this->resizeHandle().contains(event->pos()))
    {
        m_resizeHandlePressed=true;
        m_oldrect=m_rect;
        m_mouseOffset = event->scenePos();
    }
    else
    {
        m_resizeHandlePressed=false;
    }
    if(!this->flags().testFlag(ItemIsMovable))
    {
        if(this->gwfile!="")
            emit roomClicked(this->gwfile);
    }
    else
        QGraphicsItem::mousePressEvent(event);
}


void GwRectangle::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    m_resizeHandlePressed=false;
    QGraphicsItem::mouseReleaseEvent(event);

}



bool GwRectangle::collidesWithItem(const QGraphicsItem *other, Qt::ItemSelectionMode mode) const
{
    if(other->zValue()<0)
        return false;
    return QGraphicsItem::collidesWithItem(other,mode);
}
